import os
from dotenv import load_dotenv
from fastapi import FastAPI, UploadFile, File, HTTPException
from fastapi.responses import FileResponse, HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.middleware.cors import CORSMiddleware
from pathlib import Path
import logging
import logging.config
import traceback
import tempfile
import cv2

from video_processing.processor import VideoProcessor
from face_processing.face_swapper import FaceSwapper
from audio_processing.audio_translator import AudioTranslator

# Load logging configuration
logging.config.fileConfig('config/logging.conf')
logger = logging.getLogger('videoTrans')

# Load environment variables
load_dotenv()

# Create necessary directories
os.makedirs('logs', exist_ok=True)
os.makedirs('temp', exist_ok=True)
os.makedirs('output', exist_ok=True)
os.makedirs('models', exist_ok=True)

app = FastAPI(
    title="AI Video Face Swap and Translation",
    description="An API for swapping faces in videos and translating audio",
    version="1.0.0"
)

# Add CORS middleware
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# Initialize processors
video_processor = VideoProcessor(batch_size=30)  # Process 30 frames at a time
face_swapper = FaceSwapper()
audio_translator = AudioTranslator()

@app.get("/", response_class=HTMLResponse)
async def home():
    """
    Homepage with basic instructions
    """
    return """
    <html>
        <head>
            <title>AI Video Face Swap and Translation</title>
            <style>
                body {
                    font-family: Arial, sans-serif;
                    max-width: 800px;
                    margin: 0 auto;
                    padding: 20px;
                }
                code {
                    background-color: #f4f4f4;
                    padding: 2px 5px;
                    border-radius: 3px;
                }
            </style>
        </head>
        <body>
            <h1>AI Video Face Swap and Translation API</h1>
            <p>This API provides video face swapping and audio translation services.</p>

            <h2>Available Endpoints:</h2>
            <ul>
                <li><a href="/docs">/docs</a> - Interactive API documentation</li>
                <li><code>POST /process</code> - Process a video file</li>
            </ul>

            <h2>Example Usage:</h2>
            <pre>
curl -X POST "http://localhost:3000/process" \\
    -H "accept: application/json" \\
    -H "Content-Type: multipart/form-data" \\
    -F "video=@/path/to/your/video.mp4" \\
    -F "target_language=zh"
            </pre>
        </body>
    </html>
    """

@app.post("/process")
async def process_video(
    video: UploadFile = File(...),
    target_language: str = "en",
):
    """
    Process a video file by swapping faces and translating audio

    Parameters:
    - video: The input video file
    - target_language: Target language code (e.g., 'en', 'zh', 'es')

    Returns:
    - Processed video file with swapped faces and translated audio
    """
    try:
        # Create temporary directories if they don't exist
        temp_dir = Path(os.getenv("TEMP_DIR", "./temp"))
        output_dir = Path(os.getenv("OUTPUT_DIR", "./output"))
        temp_dir.mkdir(exist_ok=True)
        output_dir.mkdir(exist_ok=True)

        logger.info(f"Processing video: {video.filename}")

        # Save uploaded video
        input_path = temp_dir / video.filename
        with open(input_path, "wb") as buffer:
            content = await video.read()
            buffer.write(content)
        logger.info(f"Video saved to: {input_path}")

        # Process video frames in batches
        logger.info("Extracting and processing frames...")
        frames_generator = video_processor.extract_frames(input_path)
        processed_frames_generator = face_swapper.process_frames(frames_generator)

        # Create a temporary file to store processed frames
        with tempfile.NamedTemporaryFile(suffix='.mp4', delete=False) as temp_video:
            temp_video_path = Path(temp_video.name)

        # Get video info for proper frame writing
        video_info = video_processor.get_video_info(input_path)

        # Initialize video writer
        writer = cv2.VideoWriter(
            str(temp_video_path),
            cv2.VideoWriter_fourcc(*'mp4v'),
            video_info['fps'],
            (video_info['width'], video_info['height'])
        )

        # Write processed frames
        total_frames = 0
        try:
            for processed_batch in processed_frames_generator:
                for frame in processed_batch:
                    writer.write(frame)
                    total_frames += 1
                logger.info(f"Processed {total_frames} frames")
        finally:
            writer.release()

        # Process audio
        logger.info("Extracting audio...")
        audio_path = video_processor.extract_audio(input_path)
        if not audio_path.exists():
            raise ValueError(f"Audio extraction failed: {audio_path} not found")
        logger.info(f"Audio extracted to: {audio_path}")

        logger.info("Translating and synthesizing audio...")
        translated_audio = audio_translator.translate_and_synthesize(
            audio_path, target_language
        )
        if not translated_audio.exists():
            raise ValueError(f"Audio translation failed: {translated_audio} not found")
        logger.info(f"Translated audio saved to: {translated_audio}")

        # Combine processed frames and audio
        logger.info("Combining video and audio...")
        output_path = output_dir / f"processed_{video.filename}"
        final_path = video_processor.combine_video_audio(
            temp_video_path, translated_audio, output_path, video_info['fps']
        )
        if not final_path.exists():
            raise ValueError(f"Video combination failed: {final_path} not found")
        logger.info(f"Final video saved to: {final_path}")

        # Clean up temporary files
        if temp_video_path.exists():
            temp_video_path.unlink()

        return FileResponse(
            final_path,
            media_type="video/mp4",
            filename=f"processed_{video.filename}"
        )

    except Exception as e:
        logger.error(f"Error processing video: {str(e)}")
        logger.error(traceback.format_exc())
        raise HTTPException(status_code=500, detail=str(e))

if __name__ == "__main__":
    import uvicorn

    # Get host and port from environment variables
    host = os.getenv("HOST", "0.0.0.0")
    port = int(os.getenv("PORT", "8080"))

    logger.info(f"Starting server on {host}:{port}")
    uvicorn.run(app, host=host, port=port)